package edu.siu.math.egut.util;
 
import java.io.Serializable;
import java.util.Arrays;
 
/**
 * A data structure for storing structure constants for exceptional groups.
 * This implementation uses an int[] to store the structure constants N(a,b)
 * for positive roots a,b such that a comes before b in the int[][] which
 * 
 * 
 * @author Joe Pleso
 * 
 */
final public class StructureConstantsMatrix implements Serializable {

    private static final long serialVersionUID = 126L;
    private final int[] matrix;
    private final int n;
    private final int[][] roots;

    /**
     * Create a new matrix for storing structure constants.
     * 
     * @param size            the size of the matrix to be created
     * @param r the upper (or lower) not quite sure triangular part of the
     * matrix (strictly)
     */
    public StructureConstantsMatrix(int[][] r, int size) {/*@\label{scmconst}@*/
        n = size;
        roots = r;
        matrix = new int[((n * (n - 1)) / 2)];
    }/*@\label{scmconstend}@*/

    /**
     * Basic constructor.
     * 
     * @param r list of roots
     * @param m the matrix 
     * @param size the height (and width) of the matrix
     * 
     */
    public StructureConstantsMatrix( int[][] r, int[] m, int size) {
        roots = r;
        n = size;
        matrix = m;
    }

    /**
     * Gets the value corresponding to N(iRoot,jRoot).
     * 
     * @param iRoot            the first root
     * @param jRoot            the second root
     * @return the value of N(iRoot,jRoot)
     */
    public int get(int[] iRoot, int[] jRoot) {/*@\label{scmget}@*/
        int i = findIndex(iRoot);
        int j = findIndex(jRoot);
        
        if (j < i)
    	    return (-1 * get(jRoot, iRoot));
        i++;
        j++;
 
        return matrix[((((2 * n) - i) * (i - 1)) / 2) - i + j - 1];
    }/*@\label{scmgetend}@*/

    /**
     * Set the value at position i,j to x.
     * 
     * @param i            the row to be set
     * @param j            the column to be set
     * @param x            the new value for this position
     */
    public void set(int i, int j, int x) {/*@\label{scmset}@*/
        if (j < i)
    	    set(j, i, (-1 * x));
        else {
            i++;
    	    j++;
    	    matrix[((((2 * n) - i) * (i - 1)) / 2) - i + j - 1] = x;
        }
    }/*@\label{scmsetend}@*/
 
    
    /**
     * Finds the index of root in the int[][] roots
     * 
     * @param roots
     *            a int[][] to search in
     * @param root
     *            a int[] to find in roots
     * @return the index such that roots[index]==root is true, or -1 if a match
     *         was not found
     */
    private int findIndex(int[][] roots, int[] root) {
	for (int i = 0; i < roots.length; i++)
	    if (Arrays.equals(root, roots[i]))
		return i;
	return -1;
    }

    int findIndex(int[] root) {
	return findIndex(roots, root);
    }

    
}